import { ICustomer, ICustomerRegisterInfo } from "@src/interface";
import {DatabaseService} from '@src/db';
import { v4 as uuidv4 } from 'uuid';
import { MyError, decodeJwtToken, encrypt, genJwtToken } from "@src/tools";
import dayjs from "dayjs";

export namespace CustomerService{
    export async function getCustById(id:string):Promise<ICustomer>{
        let collection = await DatabaseService.getCollection("customer");
        let cust = await collection.get(id);
        console.log("getCustById",cust)
        return cust.content ? Object.assign({id:id},cust.content) : null;
    }
    export async function getCustByUsername(username:string):Promise<ICustomer>{
        const query = `SELECT META().id AS id,* FROM customer WHERE username = '${username}'`;
        let rows = await DatabaseService.query(query);
        console.log("getCustByUsername",rows)
        let rst = rows[0];
        return rst ? Object.assign({id:rst.id},rst.customer) : null;
    }
    export async function getCustByToken(token:string){
        if (!token) throw new MyError({code:1001,message:'token id required'});
        let decode: any = await decodeJwtToken(token);
        if (!decode?.data?.id) throw new MyError({code:1002,message:'token id invalid'});
        let cust = await getCustById(decode.data.id);
        if (!cust) throw new MyError({code:1002,message:'token id invalid'});
        if(cust.token != token) throw new MyError({code:1002,message:'token id invalid'});
        return cust;
    }
    export async function updateCustById(id:string,info:ICustomer):Promise<ICustomer>{
        let cust = await getCustById(id);
        if(!cust){
            throw new Error(`${id} not exists`);
        }
        Object.assign(cust,info);
        delete cust.id;
        let collection = await DatabaseService.getCollection("customer");
        await collection.upsert(id, cust);
        return cust;
    }
    export async function register(info:ICustomerRegisterInfo){
        if(!info?.username) throw new Error("username is required");
        if(!info?.password) throw new Error("password is required");
        if(!info?.email) throw new Error("email is required");
        if(!info?.phone) throw new Error("phone is required");
        let existed = await getCustByUsername(info.username);
        if(existed){
            throw new Error("username exists");
        }
        let cust:ICustomer=info;
        cust.salt = String(Math.floor(Math.random() * 10000));
        cust.hash = encrypt.hashPassword(cust.password, cust.salt);
        let id = uuidv4();
        let collection = await DatabaseService.getCollection("customer");
        let rst = await collection.insert(id,cust);
        return {
            id:id
        }
    }
    export async function loginByPwd(opt:{username:string;password:string;}){
        if(!opt?.username) throw new Error("username is required");
        if(!opt?.password) throw new Error("password is required");
        let existed = await getCustByUsername(opt.username);
        if(!existed){
            throw new Error("username not exists");
        }
		// 密码不对
		if (existed.hash != encrypt.hashPassword(opt.password, existed.salt)) throw new Error('password is error');
        console.log(`user[${existed.username}] login at ${dayjs().format('YYYY-MM-DD HH:mm:ss')}`);
        return await updateToken(existed.id);
    }
    export async function loginByToken(cust:ICustomer){
        console.log(`user[${cust.username}] login by token at 于${dayjs().format('YYYY-MM-DD HH:mm:ss')} 通过token登入`);
        return await updateToken(cust.id);
    }
    export async function logout(cust:ICustomer){
        await updateCustById(cust.id,{token:null});
        console.log(`user[${cust.username}] logout at ${dayjs().format('YYYY-MM-DD HH:mm:ss')}`);
    }
    async function updateToken(custId:string){
        let newToken = genJwtToken({ data: { id: custId }, exp: 7 });
        await updateCustById(custId,{token:newToken,lastLoginTime:Date.now()});
        return {
            token: newToken
        };
    }
}